package com.janlei.thread;

/**
 * 如果threadlocal.get之后的副本，只在当前线程中使用，那么是线程安全的；如果对其他线程暴露，不一定是线程安全的。
 */
public class ThreadLocalStu {

    final private ThreadLocal threadLocal = new ThreadLocal();

    void executeSerial() {
        Thread thread1 = new Thread(
                () -> {
                    System.out.println(Thread.currentThread().getName());
                    System.out.println(threadLocal.get());
                    threadLocal.set(1);
                    System.out.println(threadLocal.get());
                }
        );
        thread1.start();
        try {
            thread1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Thread thread2 = new Thread(
                () -> {
                    System.out.println(Thread.currentThread().getName());
                    System.out.println(threadLocal.get());
                    threadLocal.set(4);
                    System.out.println(threadLocal.get());
                }
        );
        thread2.start();
        try {
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    void executeConcurrency() {
        Thread thread1 = new Thread(
                () -> {
                    System.out.println(Thread.currentThread().getName());
                    System.out.println(threadLocal.get());
                    threadLocal.set(1);
                    System.out.println(threadLocal.get());
                }
        );
        Thread thread2 = new Thread(
                () -> {
                    System.out.println(Thread.currentThread().getName());
                    System.out.println(threadLocal.get());
                    threadLocal.set(4);
                    System.out.println(threadLocal.get());
                }
        );
        thread1.start();
        thread2.start();
    }

    static int isSafe() throws InterruptedException {
        ThreadLocal<Container> tl = new ThreadLocal<>();
        tl.set(new Container()); // 先set下ThreadLocal

        Container container = tl.get();
        Runnable task = () -> {
            for (int i = 0; i < 10000; i++) {
                container.num++;
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);

        t1.start();
        t1.join();
        t2.start();
        t2.join();
        return tl.get().num;
    }

    static class Container {
        int num;
    }
}


